home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2005 October / PCWOCT05.iso / Software / Resources / CutePDF 2.3 / converter.exe / GNUGS / PDF_FONT.PS < prev    next >
Text File  |  2002-04-17  |  39KB  |  1,224 lines

  1. %    Copyright (C) 1994-2002 artofcode LLC.  All rights reserved.
  2. % This software is provided AS-IS with no warranty, either express or
  3. % implied.
  4. % This software is distributed under license and may not be copied,
  5. % modified or distributed except as expressly authorized under the terms
  6. % of the license contained in the file LICENSE in this distribution.
  7. % For more information about licensing, please refer to
  8. % http://www.ghostscript.com/licensing/. For information on
  9. % commercial licensing, go to http://www.artifex.com/licensing/ or
  10. % contact Artifex Software, Inc., 101 Lucas Valley Road #110,
  11. % San Rafael, CA  94903, U.S.A., +1(415)492-9861.
  12.  
  13. % $Id: pdf_font.ps,v 1.23.2.6 2002/04/16 06:11:29 giles Exp $
  14. % pdf_font.ps
  15. % PDF font operations.
  16.  
  17. /.setlanguagelevel where { pop 2 .setlanguagelevel } if
  18. .currentglobal true .setglobal
  19. /pdfdict where { pop } { /pdfdict 100 dict def } ifelse
  20. GS_PDF_ProcSet begin
  21. pdfdict begin
  22.  
  23. % We cache the PostScript font in an additional element of the
  24. % font resource dictionary, called PSFont.
  25.  
  26. % ---------------- Encodings ---------------- %
  27.  
  28. % Apply a list of differences to an Encoding.
  29. % Note that the differences may cause the array to grow.
  30. /updateencoding {    % <encoding> <differences> updateencoding <enc'>
  31.     % Calculate the length of the result.
  32.   exch 0 2 index {
  33.     dup type /nametype ne { exch pop } { pop 1 add } ifelse
  34.   } forall
  35.   1 index length .max array dup 0 4 -1 roll putinterval
  36.   exch 0 exch {
  37.         % Stack: enc' code element
  38.     dup type /nametype ne
  39.       { exch pop }
  40.       { 3 copy put pop 1 add }
  41.     ifelse
  42.   } forall pop
  43. } bdef
  44.  
  45. % Get the Encoding for a font.
  46. /getencoding        % <base-encoding> <font-resource> getencoding <enc>
  47.  { /Encoding knownoget
  48.     { dup type /nametype eq
  49.        { 
  50.          % The published PDF specification says the Encoding name
  51.          % "must be" one of the 3 predefined Encodings, implying
  52.          % that an error should occur if it isn't.  However, Acrobat
  53.          % Reader simply ignores unknown names, and since there are
  54.          % some buggy applications that rely on this, we do the same.
  55.  
  56.          dup dup dup /MacRomanEncoding eq
  57.          exch /MacExpertEncoding eq or 
  58.          exch /WinAnsiEncoding eq or
  59.            { exch pop findencoding
  60.            }
  61.            { pop
  62.            }
  63.          ifelse
  64.        }
  65.        { dup /BaseEncoding knownoget
  66.       { findencoding 3 -1 roll pop exch
  67.       }
  68.      if
  69.      /Differences knownoget { updateencoding } if
  70.        }
  71.       ifelse
  72.     }
  73.    if
  74.  } bdef
  75.  
  76. % Rename a font with a generated name.
  77. /renamefont {        % <fontdict> renamefont <font'>
  78.   dup /FontName 2 copy get genfontname dup 5 1 roll put definefont
  79. } bind def
  80.  
  81. % Adjust a font according to the Encoding and Widths in the font resource.
  82. /adjustfont {        % <font-resource> <font> adjustfont <font'>
  83.   getfontencoding
  84.   getfontmetrics 4 -1 roll pop .updatefont { renamefont } if
  85. } bind def
  86.  
  87. % Get the (possibly modified) encoding of a font.
  88. /getfontencoding {    % <font-resource> <font> getfontencoding
  89.             %   <font-resource> <font> <Encoding|null>
  90.   1 index /Encoding known {
  91.     dup /Encoding .knownget { 2 index getencoding } { null } ifelse
  92.   } {
  93.     null
  94.   } ifelse
  95. } bdef
  96.  
  97. /find_in_diff     % <Differences> <index> find_in_diff <bool>
  98. { false exch 0 4 3 roll
  99.   { dup type /nametype ne { exch pop } { pop 1 add } ifelse
  100.     2 copy eq {
  101.       pop pop pop true 0 0 exit
  102.     } if
  103.   } forall
  104.   pop pop
  105. } bdef
  106.  
  107. % Get the metrics of a font, if specified.
  108. /getfontmetrics {    % <font-resource> <font> <Encoding|null> getfontmetrics
  109.             %   <font-resource> <font> <Encoding|null>
  110.             %   <Metrics|null>
  111.   2 index /Widths known {
  112.     dup null eq { pop dup /Encoding get } if
  113.     4 dict begin
  114.       /Encoding exch def
  115.       /Metrics Encoding length dict def
  116.       exch
  117.       dup /Widths oget /Widths exch def
  118.         % Stack: font font-res
  119.         % Note that widths are always based on a 1000-unit
  120.         % character space, but the FontMatrix may specify
  121.         % some other scale factor.  Compensate for this here,
  122.         % by scaling the Widths if necessary.
  123.       0.001 2 index /FontMatrix get 0 get div
  124.         % Stack: font font-res mscale
  125.       1 index /FirstChar oget dup 1 4 index /LastChar oget
  126.        {    % Stack: font font-res mscale first-char index
  127.      Encoding 1 index get
  128.      Widths 2 index 4 index sub oget
  129.          % Stack: font font-res mscale first-char index charname width
  130.      4 index mul
  131.         % The following 'loop' is only context for 'exit'.
  132.      {    
  133.         % Work around a bug in pdfTeX, which can generate Encoding
  134.         % vectors containing nulls :
  135.        1 index null eq { exit } if
  136.         % There is a hack here to deal with encodings where the
  137.         % same character appears more than once, because the Metrics
  138.         % dictionary works by character name, not by character code.
  139.         % We prefer to take (1) non-zero width, and (2) width for 
  140.         % the character code which appears in Differences.
  141.        Metrics 2 index .knownget not { 0 } if 0 ne {
  142.          5 index /Encoding knownoget not { exit } if
  143.          dup type /dicttype ne { pop exit } if
  144.          /Differences knownoget not { exit } if
  145.          3 index //find_in_diff exec not { exit } if
  146.        } if
  147.        2 copy Metrics 3 1 roll put
  148.        exit
  149.      } loop
  150.      pop pop pop
  151.        }
  152.       for pop
  153.         % Now fill in the MissingWidth for any encoded characters
  154.         % that aren't in Metrics already.  Note that built-in
  155.         % fonts may have Widths/FirstChar/LastChar but no
  156.         % FontDescriptor, so we must check for this.
  157.         % Stack: font font-res mscale
  158.       1 index /FontDescriptor knownoget {
  159.     Metrics exch
  160.     /MissingWidth knownoget { 2 index mul } { 0 } ifelse exch
  161.     Encoding {
  162.         % Stack: font font-res mscale missing-width metrics charname
  163.         % Work around the abovementioned pdfTeX bug.
  164.       dup null ne {
  165.         2 copy known not { 2 copy 4 index put } if pop
  166.       } {
  167.         pop
  168.       } ifelse
  169.     } forall pop pop pop
  170.       } {
  171.     pop
  172.       } ifelse
  173.     exch Encoding Metrics end
  174.   } {
  175.     null
  176.   } ifelse
  177. } bdef
  178.  
  179. currentdict /find_in_diff undef
  180.  
  181. % ---------------- Descriptors ---------------- %
  182.  
  183. % Partial descriptors for the 14 built-in fonts.  Note that
  184. % from PDF 1.1 to PDF 1.2, the meaning of the Flag 6 in the FontDescriptor
  185. % object has undergone a subtle change in its meaning which has serious
  186. % consequences for searching with Acrobat:
  187. % In PDF 1.1, the flag meant: Font has StandardEncoding
  188. % In PDF 1.2, the flag means: Font has (subset of) StandardRomanCharacterSet
  189. /standardfontdescriptors mark
  190.   /Courier mark /Flags 16#23 .dicttomark
  191.   /Courier-Oblique 1 index
  192.   /Courier-Bold 1 index
  193.   /Courier-BoldOblique 1 index
  194.   /Helvetica mark /Flags 16#20 .dicttomark
  195.   /Helvetica-Oblique 1 index
  196.   /Helvetica-Bold 1 index
  197.   /Helvetica-BoldOblique 1 index
  198.   /Times-Roman mark /Flags 16#22 .dicttomark
  199.   /Times-Bold 1 index
  200.   /Times-Italic mark /Flags 16#62 .dicttomark
  201.   /Times-BoldItalic 1 index
  202.   /Symbol mark /Flags 16#4 .dicttomark
  203.   /ZapfDingbats 1 index
  204. .dicttomark readonly def
  205.  
  206. % ---------------- Utilities ---------------- %
  207.  
  208. /.glyphpath {    % <glyphname> <boolean> .glyphpath -
  209.   % another glyphpath written in addxchar.ps does not work here...
  210.   currentfont 3 1 roll exch
  211.   currentfont dup length dict begin
  212.     { 1 index /Encoding eq { pop [ 3 -1 roll ] def } { def } ifelse } forall
  213.   currentdict end /.glyphpathfont exch definefont
  214.   setfont <00> exch charpath setfont
  215. } bdef
  216.  
  217. /makeboldfont {    % <basefont> <strokewidth> makeboldfont <boldfont>
  218.   10 dict begin
  219.     /strokewidth exch def
  220.     /basefont exch def
  221.     /FontMatrix matrix def
  222.     %/FontName basefont /FontName get def
  223.     /FontName /.boldfont def
  224.     /FontType 3 def
  225.     /Encoding basefont /Encoding get def
  226.     /FontBBox [ basefont /FontBBox get cvx exec
  227.       4 2 roll basefont /FontMatrix get transform
  228.       4 2 roll basefont /FontMatrix get transform
  229.     ] def
  230.     /BuildGlyph {
  231.       gsave
  232.       exch begin
  233.         basefont setfont
  234.         strokewidth setlinewidth
  235.         1 setlinejoin
  236.         newpath
  237.         0 0 moveto dup false .glyphpath stroke
  238.         0 0 moveto glyphshow
  239.         currentpoint setcharwidth
  240.       end
  241.       grestore
  242.     } bind def
  243.    currentdict
  244.   end
  245.   dup /FontName get exch definefont
  246. } bind def
  247.  
  248. % Fabricate a font name by adding ?'s on the end.
  249. /genfontname        % <name> genfontname <name>
  250.  { dup length string cvs
  251.     { (?) concatstrings
  252.       dup cvn FontDirectory exch known not { cvn exit } if
  253.     }
  254.    loop
  255.  } bdef
  256.  
  257. % Find a font, and adjust its encoding if necessary.
  258. /.pdfdfndict mark
  259.   /defaultfontname /Helvetica
  260. .dicttomark readonly def
  261. /pdffindfont {        % <font-resource> <fontname> pdffindfont <font>
  262.         % If the font isn't available, synthesize one based on
  263.         % its descriptor.
  264.   dup /Font resourcestatus {
  265.     pop pop findfont
  266.   } {
  267.     1 index /FontDescriptor knownoget {
  268.         % Stack: font-res fontname fontdesc
  269.       dup /Flags oget
  270.       dup 16#40 and -6 bitshift        % 1, oblique/italic
  271.       1 index 16#40000 and -17 bitshift add    % 2, bold
  272.       exch 16#2 and 2 bitshift add    % 8, serif
  273.         % We should look at the fixed flag, too.
  274.         % Stack: font-res fontname fontdesc properties
  275.       1 index /FontName oget exch
  276.         % Analyzes font name and extract "Narrow" property
  277.         % which is not described by the FontDescriptor Flags.
  278.       0 2 index .fontnameproperties 4 and or
  279.         % Rebind the default font name to Helvetica so that
  280.         % fonts with no properties are handled correctly.
  281.       //.pdfdfndict begin .substitutefontname end
  282.         % Stack: font-res fontname fontdesc substname|null
  283.       Fontmap 1 index known not {
  284.         % No available good substitution, use the standard one.
  285.     pop 1 index .substitutefont
  286.       } if
  287.       QUIET not {
  288.     (Substituting font ) print dup =only
  289.     ( for ) print 2 index =only (.) = flush
  290.       } if
  291.       3 -1 roll pop findfont
  292.         % Stack: font-res fontdesc font
  293.         % If this is a small-caps font, replace the CharString
  294.         % entries for a..z.
  295.       exch /Flags oget 16#20000 and 0 ne {
  296.     true .copyfontdict
  297.     dup /CharStrings 2 copy get dup length dict .copydict
  298.     4 index /FirstChar get 97 .max
  299.     5 index /LastChar get 122 .min 1 exch {
  300.         % Stack: font-res font' font' /CharStrings charstrings code
  301.         % Note that this only remaps a-z, not accented characters.
  302.       5 index /Widths oget 1 index 7 index /FirstChar get sub oget
  303.       1 string dup 0 5 -1 roll put
  304.         % Stack: font-res font' font' /CharStrings charstrings code
  305.         %   width (x)
  306.       2 index exch dup cvn exch
  307.       dup 0 2 copy get 32 sub put 4 -1 roll {
  308.             % Stack: operand (X) width
  309.         0 setcharwidth exch pop
  310.         currentfont /FontMatrix get matrix invertmatrix concat
  311.         0.7 dup scale 0 0 moveto show
  312.       } /exec cvx 4 packedarray cvx put
  313.     } for put
  314.     renamefont
  315.       } if
  316.     } {
  317.         % No descriptor available, use the default algorithm.
  318.       findfont
  319.     } ifelse
  320.   } ifelse adjustfont
  321. } bdef
  322. /findpdffont {    % <font-resource> <fontname> findpdffont <font>
  323.   {} 3 1 roll            % proc fnres fnname
  324.   [
  325.     [ (,Bold)        { .03 makeboldfont } ]
  326.     [ (,BoldItalic)    { .03 makeboldfont [ 1 0 .3 1 0 0 ] makefont } bind ]
  327.     [ (,Italic)        { [ 1 0 .3 1 0 0 ] makefont } bind ]
  328.   ] {
  329.     1 index dup length string cvs
  330.     1 index 0 get tailmatch {    % proc fnres fnname []
  331.       3 -1 roll pop exch 1 get    % proc fnres pre-fnname proc
  332.       4 -1 roll pop 3 1 roll    % proc fnres pre-fnname
  333.       exit
  334.     } { pop pop } ifelse     % proc fnres fnname
  335.   } forall
  336.   pdffindfont exch exec
  337. } bdef
  338.  
  339. % ---------------- Type 1 fonts ---------------- %
  340.  
  341. /buildType1        % <Type1-font-resource> buildType1 <font>
  342.  { dup /BaseFont get pdffindfont
  343.  } bdef
  344.  
  345. % The state dictionary for the embedded Type 1 font reading procedure
  346. % has the following keys and values:
  347. %    data - stream (filter)
  348. %    buffer, buffer2 - string
  349. %    hexify - procedure to convert buffer to hex if needed
  350. %    leftstr - string containing (non-negative) integer
  351. %    sectionstr - string containing a character 0 .. 3
  352. %    stream - (stream) dictionary
  353. %    proc - procedure of the form {-dict- type1read}
  354. %       pfbhdr - string containing 16#80 if PFB, 0 otherwise
  355. % When the procedure is executing, this dictionary is current.
  356. % leftstr and sectionstr are strings so that we can change their values
  357. % reliably in case the font executes a restore!
  358. % We also have to do something special about embedded fonts that
  359. % execute definefont more than once -- that is the function of topFontDict.
  360.  
  361. % Read an embedded Type 1 font.
  362. /readfontfilter {    % <proc> readfontfilter <filter>
  363.   0 () /SubFileDecode filter
  364. } bdef
  365. /readtype1dict 5 dict dup begin
  366.   /definefont {
  367.     dup topFontDict eq topFontDict null eq or {
  368.       dup wcheck not { dup length dict copy } if
  369.       exch pop savedFontName exch
  370.     } if
  371.     //systemdict /definefont get exec
  372.   } bdef
  373.   /eexec {
  374.     % Assume the font dictionary is directly below the file on the stack
  375.     count 0 gt { /topFontDict 2 index cvlit store } if
  376.     55665 /eexecDecode filter
  377.     //systemdict begin readtype1dictcopy begin cvx stopped
  378.     currentdict readtype1dictcopy eq { end } if
  379.     currentdict //systemdict eq { end } if
  380.      { stop } if
  381.   } bdef
  382. end readonly def
  383. /readtype1 {        % <font-resource> <stream-dict> readtype1 <font>
  384.         % Read the definition, using a procedure-based filter
  385.         % that turns binary/hex conversion on and off
  386.         % at the right times.
  387.    1 index exch
  388.    PDFfile fileposition 3 1 roll
  389.    11 dict begin
  390.      /leftstr (          ) 10 string copy def
  391.        dup /Length1 oget leftstr cvs pop
  392.      /sectionstr <00> 1 string copy def
  393.      /pfbhdr <00> 1 string copy def
  394.      /stream 1 index def
  395.      true resolvestream /data exch def
  396.      /buffer 1000 string def        % arbitrary
  397.      /buffer2 buffer length 2.1 div cvi 1 sub string def
  398.      /hexify /buf2hex load def
  399.    currentdict end
  400.    /type1read cvx 2 array astore cvx dup 0 get /proc 2 index put
  401.    readfontfilter
  402.         % Some buggy embedded fonts leave extra junk on the stack,
  403.         % so we have to make a closure that records the stack depth
  404.         % in a fail-safe way.
  405.    //systemdict begin
  406.         % The PDF specification is somewhat muddy about whether
  407.         % an embedded font's name is supposed to be the BaseFont
  408.         % from the Font object or the FontName from the descriptor.
  409.         % Acrobat Distiller requires the former.  Save away the
  410.         % name so we can substitute it at definefont time.
  411.    //readtype1dict dup length 3 add dict copy begin
  412.    1 index /BaseFont oget /savedFontName exch def
  413.    /topFontDict null def
  414.    /readtype1dictcopy currentdict def
  415.     { run } aload pop count 1 sub 2 packedarray cvx exec
  416.    end end
  417.    count exch sub { pop } repeat
  418.    PDFfile 3 -1 roll setfileposition
  419.    /BaseFont oget findfont
  420.    adjustfont
  421.  } bdef
  422.  
  423. % Execute the appropriate reading procedure.
  424. /type1read        % <dict> type1read <string>
  425.  { begin leftstr cvi
  426.     { type1read0 type1read1 type1read2 type1read3 } sectionstr 0 get get exec
  427.    (          ) leftstr copy cvs pop end
  428.  } bdef
  429.  
  430. % Read the next block of data into the buffer.
  431. /type1readdata        % <left> <buffer> type1readdata <substring> <left'>
  432.  { 0 2 index 2 index length .min getinterval
  433.         % Adobe requires readstring to signal an error if given
  434.         % an empty string.  Work around this nonsense here.
  435.    dup length 0 ne { data exch readstring pop } if
  436.    dup length 3 -1 roll exch sub
  437.    DEBUG
  438.     { dup =only ( read ) print
  439.       1 index length =only (: ) print
  440.       1 index == flush
  441.     } if
  442.  } bdef
  443.  
  444. % Read the initial byte to see if we need to skip a 6 byte PFB header
  445. /type1read0 {         % <left> type1read0 <string> <left'>
  446.   sectionstr 0 1 put    % either way we go to the next stage
  447.   pfbhdr type1readdata
  448.   1 index 0 get 16#80 eq {
  449.     (\n   **** Warning: Embedded Type1 font in PFB format is not valid PDF.)
  450.     pdfformaterror
  451.     DEBUG { (skipping PFB header) = flush } if
  452.     exch pop buffer 0 5 getinterval type1readdata exch
  453.     dup 4 get 256 mul 1 index 3 get add 256 mul
  454.     1 index 2 get add 256 mul 1 index 1 get add
  455.     DEBUG { (PFB segment length = ) print dup = } if
  456.     exch pop  % discard the string keeping the PFB segment length
  457.     2 copy ne {
  458.       (\n   **** Warning: Type 1 PFB segment length and Length 1 value do not match.)
  459.       pdfformaterror
  460.       exch     % keep the PFB length instead
  461.     } if
  462.     pop
  463.     buffer type1readdata    % go ahead and read a block
  464.   }
  465.   if    % if not PFB, return pfbhdr string (first char of file, usually %).
  466. } bdef
  467.  
  468. % Read the next block of the initial text portion.
  469. /type1read1 {        % <left> type1read1 <string> <left'>
  470.   DEBUG { (read1 ) print } if
  471.   dup 0 eq {
  472.     pop sectionstr 0 2 put
  473.     stream /Length2 oget
  474.             % Determine whether to hexify data for eexec.
  475.     dup 8 lt {
  476.       type1read2    % Hexify.
  477.     } {
  478.       DEBUG { (read2 ) print } if
  479.       pfbhdr 0 get 16#80 eq {
  480.         % eat 6 more bytes of PFB junk before proceeding
  481.     DEBUG { (skipping PFB header in segment 2) = flush } if
  482.     buffer 0 6 getinterval type1readdata exch
  483.         dup 5 get 256 mul 1 index 4 get add 256 mul
  484.     1 index 3 get add 256 mul 1 index 2 get add
  485.         DEBUG { (PFB segment length = ) print dup = } if
  486.     exch pop  % discard the string keeping the PFB segment length
  487.     2 copy ne {
  488.           (\n   **** Warning: Type 1 PFB segment length and Length 2 value do not match.)
  489.           pdfformaterror
  490.       dup =
  491.       exch         % keep the PFB length instead
  492.     } if
  493.       pop
  494.       } if
  495.       buffer2 type1readdata exch
  496.             % The check doesn't have to be 100% accurate:
  497.             % hexifying is always OK.
  498.       dup 0 8 getinterval 0 exch { or } forall
  499.       128 ge {
  500.     /hexify { } store
  501.     /buffer2 buffer def    % We don't need an intermediate buffer.
  502.       } if hexify exch
  503.     } ifelse
  504.   } {
  505.     buffer type1readdata
  506.   } ifelse
  507. } bdef
  508.  
  509. % Convert a string from binary to hex for eexec.
  510. % Free variables: buffer.
  511. /buf2hex {        % <string> buf2hex <hexstring>
  512.   buffer /ASCIIHexEncode filter dup 3 -1 roll writestring closefile
  513.   buffer (>) search pop exch pop exch pop
  514. } bdef
  515.  
  516. % Read the next block of the encrypted portion.
  517. /type1trailer
  518. (0000000000000000000000000000000000000000000000000000000000000000\n\
  519. 0000000000000000000000000000000000000000000000000000000000000000\n\
  520. 0000000000000000000000000000000000000000000000000000000000000000\n\
  521. 0000000000000000000000000000000000000000000000000000000000000000\n\
  522. 0000000000000000000000000000000000000000000000000000000000000000\n\
  523. 0000000000000000000000000000000000000000000000000000000000000000\n\
  524. 0000000000000000000000000000000000000000000000000000000000000000\n\
  525. 0000000000000000000000000000000000000000000000000000000000000000\n\
  526. cleartomark\n)
  527. readonly def
  528. /type1read2 {        % <left> type1read2 <string> <left'>
  529.   DEBUG { (read2 ) print } if
  530.    dup 0 eq
  531.     { pop sectionstr 0 3 put
  532.       stream /Length3 oget
  533.       dup 0 eq
  534.        { DEBUG { (trailer ) print } if
  535.      type1trailer exch
  536.        }
  537.        { 
  538.          pfbhdr 0 get 16#80 eq {
  539.            % eat 6 more bytes of PFB junk before proceeding
  540.        DEBUG { (skipping PFB header in segment 3) = flush } if
  541.        buffer 0 6 getinterval type1readdata exch
  542.            dup 5 get 256 mul 1 index 4 get add 256 mul
  543.        1 index 3 get add 256 mul 1 index 2 get add
  544.            DEBUG { (PFB segment length = ) print dup = } if
  545.        exch pop  % discard the string keeping the PFB segment length
  546.        2 copy ne {
  547.            (\n   **** Warning: Type 1 PFB segment length and Length 3 value do not match.)
  548.            pdfformaterror
  549.          exch     % keep the PFB length instead
  550.        } if
  551.        pop
  552.        (\n) pdfformaterror
  553.          } if
  554.          type1read3
  555.        }
  556.       ifelse
  557.     }
  558.     { buffer2 type1readdata exch hexify exch
  559.     }
  560.    ifelse
  561. } bdef
  562.  
  563. % Read the next block of the final text portion.
  564. % When finished, this procedure returns an empty string.
  565. /type1read3        % <left> type1read3 <string> <left'>
  566.  { DEBUG { (read3 ) print } if
  567.    buffer type1readdata
  568.  } bdef
  569.  
  570. % ---------------- Type 3 fonts ---------------- %
  571.  
  572. /.notdefEncoding 256 { /.notdef } repeat 256 packedarray def
  573.  
  574. /buildType3 {        % <Type3-font-resource> buildType3 <font>
  575.   8 dict begin
  576.     /FontType 3 def
  577.     /Resources 1 index /Resources knownoget { oforce } { 0 dict } ifelse def
  578.     /FontBBox 1 index /FontBBox get cvx def
  579.     /FontMatrix 1 index /FontMatrix oget def
  580.     /CharProcs 1 index /CharProcs oget def
  581.     1 index /Widths knownoget {
  582.       /Widths exch def
  583.       /FirstChar 1 index /FirstChar oget def
  584.       /LastChar 1 index /LastChar oget def
  585.     } if
  586.     /FontName 1 index /Name get genfontname def
  587.     /Encoding .notdefEncoding 2 index getencoding def
  588.         % We have to define BuildChar rather than BuildGlyph:
  589.         % there is no PDF equivalent of glyphshow, and we need
  590.         % the character code to access the Widths.
  591.     /BuildChar {
  592.         % Stack: font charcode
  593.       1 index begin 3 dict begin
  594.       /Font 3 -1 roll def /CharCode 1 index def
  595.       % Make unknown characters map to /.notdef
  596.       Encoding exch get dup CharProcs exch known
  597.         { CharProcs exch oget }
  598.     { pop CharProcs /.notdef oget }
  599.       ifelse
  600.       PDFfile fileposition exch
  601.       false resolvestream
  602.         % Stack: filepos stream
  603.         % Don't let setgcolor set the color inside the BuildGlyph
  604.         % procedure, because this causes an /undefined error.
  605.       q null /FillColor gput null /StrokeColor gput
  606.       Font /Resources get exch pdfopdict .pdfruncontext
  607.       Q
  608.       PDFfile exch setfileposition
  609.       end end
  610.     } bdef
  611.     FontName currentdict end definefont exch pop
  612. } bdef
  613. /.adjustcharwidth {    % <wx> <wy> .adjustcharwidth <wx'> <wy'>
  614.   /Widths where {
  615.     begin
  616.     CharCode FirstChar ge CharCode LastChar le and {
  617.       exch pop Widths CharCode FirstChar sub get exch
  618.     } if end
  619.   } if
  620. } bdef
  621.  
  622. % ---------------- TrueType fonts ---------------- %
  623.  
  624. /TTfonts mark
  625.   /Arial /Helvetica
  626.   /Arial,Italic /Helvetica-Oblique
  627.   /Arial,Bold /Helvetica-Bold
  628.   /Arial,BoldItalic /Helvetica-BoldOblique
  629.   /CourierNew /Courier
  630.   /CourierNew,Bold /Courier-Bold
  631.   /TimesNewRoman /Times-Roman
  632.   /TimesNewRoman,Italic /Times-Italic
  633.   /TimesNewRoman,Bold /Times-Bold
  634.   /TimesNewRoman,BoldItalic /Times-BoldItalic
  635.   %
  636.   /ArialBlack,Italic /Arial-BlackItalic
  637.   /ArialNarrow,Bold /ArialNarrow-Bold
  638.   /ArialNarrow,BoldItalic /ArialNarrow-BoldItalic
  639.   /ArialNarrow,Italic /ArialNarrow-Italic
  640.   /BookAntiqua,Bold /BookAntiqua-Bold
  641.   /BookAntiqua,BoldItalic /BookAntiqua-BoldItalic
  642.   /BookAntiqua,Italic /BookAntiqua-Italic
  643.   /BookmanOldStyle,Bold /BookmanOldStyle-Bold
  644.   /BookmanOldStyle,BoldItalic /BookmanOldStyle-BoldItalic
  645.   /BookmanOldStyle,Italic /BookmanOldStyle-Italic
  646.   /CenturyGothic,Bold /CenturyGothic-Bold
  647.   /CenturyGothic,BoldItalic /CenturyGothic-BoldItalic
  648.   /CenturyGothic,Italic /CenturyGothic-Italic
  649.   /ComicSansMS,Bold /ComicSansMS-Bold
  650.   /CourierNew,Bold /CourierNewPS-BoldMT
  651.   /CourierNew,BoldItalic /CourierNewPS-BoldItalicMT
  652.   /CourierNew,Italic /CourierNewPS-ItalicMT
  653.   /FranklinGothicMedium,Italic /FranklinGothic-MediumItalic
  654.   /Garamond,Bold /Garamond-Bold
  655.   /Garamond,Italic /Garamond-Italic
  656.   /Georgia,Bold /Georgia-Bold
  657.   /Georgia,BoldItalic /Georgia-BoldItalic
  658.   /Georgia,Italic /Georgia-Italic
  659.   /Tahoma,Bold /Tahoma-Bold
  660.   /TrebuchetMS,Bold /TrebuchetMS-Bold
  661.   /TrebuchetMS,BoldItalic /Trebuchet-BoldItalic
  662.   /TrebuchetMS,Italic /TrebuchetMS-Italic
  663.   /Verdana,Bold /Verdana-Bold
  664.   /Verdana,BoldItalic /Verdana-BoldItalic
  665.   /Verdana,Italic /Verdana-Italic
  666. .dicttomark readonly def
  667.  
  668. /buildTrueType {    % <TrueType-font-resource> buildTrueType <font>
  669.   dup /BaseFont get
  670.   dup TTfonts exch .knownget {
  671.     exch pop
  672.         % Hack required by the PDF specification: if the
  673.         % font resource has Subtype = /TrueType but the actual
  674.         % (installed) font is not a TrueType font, ignore the
  675.         % Encoding in the font resource.  However, all current
  676.         % versions of Acrobat Reader have the 14 base TrueType
  677.         % fonts built in, so this produces incorrect output for
  678.         % badly designed PDF files that specify these file names
  679.         % with /Subtype = /TrueType but no embedded definition.
  680.         % Compensate for this by removing the /Subtype key when
  681.         % looking up the font.
  682.     exch dup length dict copy dup /Subtype null put exch
  683.   } if
  684.   pdffindfont    % findfont for PDF
  685.   % disable the auto-bold and auto-italic since it sometimes applies
  686.   % so an already bold or italic substitute font
  687.   %findpdffont    % findfont and auto-bold and/or auto-italic font for PDF
  688. } bdef
  689.  
  690. % Read an embedded TrueType font.
  691. /readtruetype {        % <font-resource> <stream-dict> readtruetype <font>
  692.         % This is much simpler than readtype1, because we don't
  693.         % have to deal with the tripartite .PFB format.
  694.   1 index exch
  695.   PDFfile fileposition 3 1 roll
  696.   true resolvestream readfontfilter
  697.         % Stack: filepos fontres stream
  698.   1 index /Subtype get /CIDFontType2 eq {
  699.     .loadttcidfont
  700.         % Stack: filepos fontres cidfont
  701.     1 index /CIDToGIDMap knownoget {
  702.       dup /Identity eq {
  703.     pop
  704.       } {
  705.     true resolvestream
  706.         % The following doesn't work for CIDToGIDMaps with more
  707.         % than 32K-1 entries.  We'll fix it later if necessary.
  708.         % Stack: filepos fontres font mapstream
  709.     dup 2 index /CIDCount oget 2 mul string readstring pop exch closefile
  710.     exch dup length 5 add dict .copydict
  711.     dup /FID undef
  712.     dup /CIDMap 4 -1 roll put
  713.     dup /CIDFontName get exch /CIDFont defineresource
  714.       } ifelse
  715.     } if
  716.   } {
  717.     null 2 index getencoding .loadpdfttfont
  718.   } ifelse
  719.   exch pop
  720.   PDFfile 3 -1 roll setfileposition
  721.         % Ignore both the Encoding and the Widths.
  722.   exch pop
  723. } bdef
  724.  
  725. % ---------------- Type 0 fonts ---------------- %
  726.  
  727. % Predefine the known CMaps, but only create them on demand.
  728. /knownCMaps mark
  729.   /Identity-H { /Identity-H 0 makeIdentityCMap }
  730.   /Identity-V { /Identity-V 1 makeIdentityCMap }
  731. .dicttomark def
  732.  
  733. /makeIdentityCMap {        % <cmapname> <wmode> .makeIdentityCMap -
  734.   .currentglobal true .setglobal 3 1 roll
  735.   /CIDInit /ProcSet findresource begin
  736.   12 dict begin
  737.     begincmap
  738.     /WMode exch def
  739.     /CMapName exch def
  740.     /CIDSystemInfo 3 dict dup begin
  741.       /Registry (Adobe) def
  742.       /Ordering (Identity) def
  743.       /Supplement 0 def
  744.     end def
  745.     %/CMapName (see above)
  746.     /CMapVersion 1 def
  747.     /CMapType 1 def
  748.     %WMode (see above)
  749.     % The PDF documentation says that these CMaps map CIDs
  750.     % "1 to 65,536".  This is a misprint for 0 to 65,535.
  751.     1 begincodespacerange
  752.     % <0001> <00ff>  <0100> <ffff>
  753.       <0000> <ffff>
  754.     endcodespacerange
  755.     1 begincidrange
  756.     % <0001> <00ff> 1   <0100> <ffff> 256
  757.       <0000> <ffff> 0
  758.     endcidrange
  759.     endcmap
  760.     CMapName currentdict /CMap defineresource
  761.     knownCMaps CMapName 2 index put
  762.   end        % CMap
  763.   end        % CIDInit ProcSet
  764.   exch .setglobal
  765. } bdef
  766.  
  767. /buildType0 {        % <Type0-font-resource> buildType0 <font>
  768.   dup /BaseFont get    % FontName
  769.   1 index /Encoding oget
  770.   dup type /nametype eq {
  771.     dup /CMap resourcestatus {
  772.     pop pop /CMap findresource
  773.     } {
  774.     knownCMaps 1 index .knownget
  775.       { exch pop exec } { /undefined signalerror } ifelse
  776.     } ifelse
  777.   } {
  778.     PDFfile fileposition exch
  779.     dup /CMapName get exch true resolvestream cvx exec
  780.     /CMap findresource
  781.     exch PDFfile exch setfileposition
  782.   } ifelse        % CMap
  783.   [
  784.     3 index /DescendantFonts oget { exec resourcefont } forall
  785.   ]            % subfonts
  786.   composefont
  787.         % Stack: fontres font
  788.   1 index /FontMatrix knownoget {
  789.     dup aload pop true {0 0 1 0 0 1} {3 -1 roll eq and} forall {
  790.       1 index exch makefont exch /FontName get exch definefont
  791.     } {
  792.       pop
  793.     } ifelse
  794.   } if exch pop
  795. } bdef
  796.  
  797. % ---------------- CIDFontType0/2 fonts ---------------- %
  798.  
  799. % Insert metrics into a CIDFont, by saving the PDF W, W2, DW, and DW2
  800. % arrays and using a (currently very inefficient) CDevProc.
  801. % For detail, refer "PDF Reference" third edition, p. 337,
  802. % "5.6.3 CIDFonts" and table "Entries in a CIDFont dictionary".
  803.  
  804. /.pdfDefaultDW  1000 def
  805. /.pdfDefaultDW2 [ 880 -1000 ] def
  806.  
  807. /addCIDmetrics {    % <CIDFont-resource> <CIDFont> addCIDmetrics <fontdict>
  808.   dup length 5 add dict .copydict
  809.   dup /FID undef
  810.   dup /UniqueID undef
  811.   dup /XUID undef
  812.     % Insert the widths into the font.
  813.  
  814.     % Stack: pdfresource newfont
  815.  
  816.   1 index /DW .knownget {
  817.     1 index /DW 3 -1 roll put
  818.     } {
  819.     dup /DW .pdfDefaultDW put
  820.     } ifelse
  821.  
  822.  
  823.   1 index /W .knownget {
  824.     dup 2 index /W 3 -1 roll put
  825.     .pdfMakeInternalW 1 index /.internalW 3 -1 roll put
  826.   } if
  827.  
  828.  
  829.   1 index /DW2 .knownget {
  830.     1 index /DW2 3 -1 roll put
  831.   } {
  832.     dup /DW2 .pdfDefaultDW2 put
  833.   } ifelse
  834.  
  835.  
  836.   1 index /W2 .knownget {
  837.     dup 2 index /W2 3 -1 roll put
  838.     .pdfMakeInternalW2 1 index /.internalW2 3 -1 roll put
  839.   } if
  840.  
  841.  
  842.   dup /CDevProc 1 index /CIDWProc load /exec load 3 packedarray cvx put
  843.   exch pop
  844. } bdef
  845.  
  846. /.pdfMakeInternalMTXArray { % <mtx_array> <item_size> .pdfConvertInternalW <mtx_array'>
  847.  
  848.   % convert /W or /W2 to internal expression
  849.   %
  850.   %   mtx_array: original /W or /W2 array
  851.   %   item_size: number of metrics values per CID
  852.   %
  853.   %   for detail of the metrics list format in PDF,
  854.   %   refer PDF Ref. p.317 "Glyph Metrics in CIDFonts".
  855.   % 
  856.   %   format of single entry in internal expression
  857.   %
  858.   %     [
  859.   %       [cid_begin cid_end]
  860.   %       value_is_varied (bool)
  861.   %       [ [values for cid_begin...]
  862.   %         [values for cid_begin + 1]
  863.   %         ... ]
  864.   %     ]
  865.   %
  866.  
  867.   7 dict
  868.   begin
  869.     /itemSize exch def
  870.     /M exch def            % original /W or /W2
  871.     /Msize M length def
  872.     /Mi { M i get } def        % W[i]
  873.     /Mi1 { M i 1 add get } def    % W[i + 1]
  874.     /putMTXEntry <<
  875.       /arraytype   {
  876.          [
  877.            [Mi Mi Mi1 length add 1 sub]
  878.            true
  879.            [
  880.              0 itemSize Mi1 length 1 sub {
  881.                [ exch 1 1 index itemSize add 1 sub { Mi1 exch get } for ]
  882.              } for
  883.            ]
  884.          ]
  885.          /i i 2 add def
  886.       }
  887.       /integertype {
  888.          [
  889.            [Mi Mi1]
  890.            false
  891.            [[ i 2 add 1 i 1 add itemSize add { M exch get } for ]]
  892.          ]
  893.          /i i 3 add def
  894.       }
  895.     >> def
  896.  
  897.     /i 0 def
  898.  
  899.     [ { putMTXEntry Mi1 type get exec i Msize ge { exit } if } loop ]
  900.   end
  901. } def
  902.  
  903. /.pdfMakeInternalW  { dup length 0 gt { 1 .pdfMakeInternalMTXArray } if } def
  904. /.pdfMakeInternalW2 { dup length 0 gt { 3 .pdfMakeInternalMTXArray } if } def
  905.  
  906. /.pdfGetMTXByCID { % <internalMTXArray> <cid>
  907.                    %     .pdfGetMTXByCID
  908.                    %         { <MTXEntry> true | false }
  909.  
  910.   % get values for given CID from internal format of /W or /W2
  911.  
  912.   exch
  913.   {
  914.     {
  915.       dup 0 get {} forall      % Stack: <cid> <entry> <cid_0> <cid_1>
  916.       3 index lt { pop pop false exit } if
  917.       2 index exch sub dup 0 lt { pop pop false exit } if
  918.       1 index 1 get not { pop 0 } if
  919.       exch 2 get exch get true exit
  920.     } loop
  921.     { exit } if
  922.   } forall
  923.   dup type /arraytype eq { exch pop true } { pop false } ifelse
  924. } def
  925.  
  926.  
  927. % Apply the [D]W[2] metrics to a character before displaying.
  928. /CIDWProc {        % <w0x> <w0y> <llx> <lly> <urx> <ury>
  929.             %   <w1x> <w1y> <vx> <vy> <cid> <font> CIDWproc
  930.             %   <w0x'> ... <vy'>
  931.  
  932.   begin % push <font> to currentdict
  933.     % <w1x> <w1y> <vx> <vy> won't be used and replaced, discard now
  934.     5 1 roll pop pop pop pop
  935.  
  936.     {
  937.       currentdict /DW .knownget not {   % no DW
  938.         .pdfDefaultDW exit              % replace <w0x> by defaultDW
  939.       } if
  940.  
  941.       currentdict /.internalW .knownget not {    % no W
  942.         exit                            % use already-stacked DW
  943.       } if
  944.  
  945.       dup length 0 eq {                 % W is null array
  946.         pop                             % discard unusable W
  947.         exit                            % use already-stacked DW
  948.       } if
  949.  
  950.       % W is finite array, try to get W_cid
  951.       2 index .pdfGetMTXByCID {           % got W, discard DW
  952.         exch pop {} forall
  953.         exit
  954.       } if
  955.  
  956.       exit
  957.     } loop
  958.  
  959.     1000 div                    % <w0x'> (normalized W)
  960.     0                           % <w0y'>
  961.  
  962.     % Stack: <w0x> <w0y> <llx> <lly> <urx> <ury> <cid> <w0x'> <w0y'>
  963.     9 -2 roll pop pop           % discard <w0x> <w0y>
  964.     7  2 roll                   % put <w0x'> <w0y'>
  965.  
  966.     % Stack: <w0x'> <w0y'> <llx> <lly> <urx> <ury> <cid>
  967.     0                           % <w1x'>
  968.     exch                        % put <w1x'>
  969.  
  970.     % Stack: <w0x'> <w0y'> <llx> <lly> <urx> <ury> <w1x'> <cid>
  971.     {
  972.       currentdict /DW2 .knownget not {  % no DW2, use defaultDW2
  973.         .pdfDefaultDW2 exit
  974.       } if
  975.  
  976.       currentdict /.internalW2 .knownget not {   % has DW2, no W2
  977.         exit                            % use already-stacked DW2
  978.       } if
  979.  
  980.       dup length 0 eq {                 % W2 is null array
  981.         pop                             % discard unusable W2
  982.         exit                            % use already-stacked DW2
  983.       } if
  984.  
  985.       2 index .pdfGetMTXByCID {        % got W2_cid, discard DW2
  986.         exch pop
  987.         exit
  988.       } if
  989.  
  990.       % could not get W2_cid
  991.       exit
  992.  
  993.     } loop
  994.  
  995.     exch pop                            % discard <cid>
  996.  
  997.  
  998.     % Stack: <w0x'> <w0y'> <llx> <lly> <urx> <ury> <w1x'> { [<vy'> <w1y'>] | [<w1y'> <vx'> <vy'>] }
  999.     dup length 2 eq {                   % this is DW2
  1000.       {1000 div} forall exch
  1001.       4 index 7 index add 2 div         % <vx'> = (<urx> + <llx>) / 2
  1002.       exch
  1003.     }{                                  % assume W2
  1004.       {1000 div} forall
  1005.     } ifelse
  1006.   end                                   % recover currentdict
  1007.  
  1008. } def
  1009.  
  1010.  
  1011.  
  1012. %----------------------------------------------------------------
  1013.  
  1014. % <string> <match> tailmatch ==> <pre> true
  1015. %                            ==> <string> false
  1016. /tailmatch {
  1017.   2 copy length 1 index length .min
  1018.   dup 2 index length exch sub exch getinterval
  1019.   1 index eq {
  1020.     length 1 index length exch sub
  1021.     0 exch getinterval true
  1022.   } {
  1023.     pop false
  1024.   } ifelse
  1025. } bind def
  1026.  
  1027. /makeboldcidfont {
  1028.   16 dict begin
  1029.     /strokewidth exch def
  1030.     /basecidfont exch def
  1031.     /FontMatrix [ 1 0 0 1 0 0 ] def
  1032.  
  1033.     /CIDFontName /.boldfont def
  1034.     /CIDFontType 1 def
  1035.  
  1036.     /basefont-H /.basefont-H /Identity-H [ basecidfont ] composefont def
  1037.     /basefont-V /.basefont-V /Identity-V [ basecidfont ] composefont def
  1038.  
  1039.     /CIDSystemInfo dup basecidfont exch get def
  1040.     /FontBBox [ basecidfont /FontBBox get cvx exec
  1041.       4 2 roll basecidfont /FontMatrix get transform
  1042.       4 2 roll basecidfont /FontMatrix get transform
  1043.     ] def
  1044.  
  1045.     /tmpstr 2 string def
  1046.     /BuildGlyph {
  1047.       gsave
  1048.       exch begin
  1049.         dup 256 idiv tmpstr exch 0 exch put
  1050.         256 mod tmpstr exch 1 exch put
  1051.         rootfont /WMode known { rootfont /WMode get 1 eq } { false } ifelse
  1052.         { basefont-V } { basefont-H } ifelse setfont
  1053.         strokewidth setlinewidth
  1054.         1 setlinejoin
  1055.         newpath
  1056.         0 0 moveto tmpstr false charpath stroke
  1057.         0 0 moveto tmpstr show
  1058.         currentpoint setcharwidth
  1059.       end
  1060.       grestore
  1061.     } bind def
  1062.  
  1063.    currentdict
  1064.   end
  1065.   dup /CIDFontName get exch /CIDFont defineresource
  1066. } bind def
  1067.  
  1068. % <CIDFont-resource> <CIDFontName> findCIDFont <CIDFont-resource> <font>
  1069. %   CIDFont-resource is not modified.
  1070. /findCIDFont {
  1071.   {
  1072.     dup /CIDFont resourcestatus {
  1073.       pop pop /CIDFont findresource
  1074.       exit
  1075.     } if
  1076.  
  1077.     dup dup length string cvs
  1078.     (,Bold) tailmatch {
  1079.       exch pop
  1080.       cvn findCIDFont 0.03 makeboldcidfont
  1081.       exit
  1082.     } if
  1083.     (,Italic) tailmatch {
  1084.       exch pop
  1085.       cvn findCIDFont
  1086.       [ 1 0 0.3 1 0 0 ] makefont
  1087.       exit
  1088.     } if
  1089.     (,BoldItalic) tailmatch {
  1090.       exch pop
  1091.       cvn findCIDFont 0.03 makeboldcidfont
  1092.       [ 1 0 0.3 1 0 0 ] makefont
  1093.       exit
  1094.     } if
  1095.     pop
  1096.  
  1097.     1 index /CIDSystemInfo get begin Registry (-) Ordering end
  1098.     concatstrings concatstrings
  1099.     cvn
  1100.     QUIET not {
  1101.       (Substituting ) print dup ==only
  1102.       ( for ) print 1 index ==only (.\n) print
  1103.     } if
  1104.     exch pop
  1105.     /CIDFont findresource
  1106.     exit
  1107.   } loop
  1108. } bdef
  1109.  
  1110. /buildCIDType0 {    % <CIDFontType0-font-resource> buildCIDType0 <font>
  1111.   dup /BaseFont get exch 1 index findCIDFont
  1112.   addCIDmetrics /CIDFont defineresource
  1113. } bdef
  1114.  
  1115. /buildCIDType2 {    % <CIDFontType2-font-resource> buildCIDType2 <font>
  1116.   dup /BaseFont get exch 1 index findCIDFont
  1117.   addCIDmetrics /CIDFont defineresource
  1118. } bdef
  1119.  
  1120. % ---------------- Other embedded fonts ---------------- %
  1121.  
  1122. /fontloadprocs mark
  1123.   /Type1C /readType1C cvx
  1124.   /CIDFontType0C /readCIDFontType0C cvx
  1125. .dicttomark readonly def
  1126.  
  1127. % Read an embedded compressed font.
  1128. /readType1C {        % <font-resource> <stream-dict> readType1C <font>
  1129.   1 index exch
  1130.   PDFfile fileposition 3 1 roll
  1131.   dup true resolvestream dup readfontfilter
  1132.         % Stack: pos resource streamdict stream filter
  1133.   3 index /FontDescriptor oget /FontName oget
  1134.   1 index FRD
  1135.   closefile closefile pop
  1136.   PDFfile 3 -1 roll setfileposition
  1137.   /FontDescriptor oget /FontName oget findfont
  1138.   adjustfont
  1139. } bdef
  1140.  
  1141. % Read an embedded CFF CIDFont.
  1142. /readCIDFontType0C {  % <font-resource> <stream-dict> readCIDFontType0C <font>
  1143.   PDFfile fileposition 3 1 roll
  1144.   dup true resolvestream dup readfontfilter
  1145.         % Stack: pos resource streamdict stream filter
  1146.   3 index /FontDescriptor oget /FontName oget
  1147.   1 index FRD
  1148.   closefile closefile pop
  1149.   PDFfile 3 -1 roll setfileposition
  1150.         % Some broken Adobe software produces PDF files in which
  1151.         % the FontName of the CFF font and the FontName in the
  1152.         % FontDescriptor don't match the BaseFont in the font.
  1153.         % Use the FontName, rather than the BaseFont, here.
  1154.   dup /FontDescriptor oget /FontName oget /CIDFont findresource
  1155.   addCIDmetrics dup /CIDFontName get exch /CIDFont defineresource
  1156. } bdef
  1157.  
  1158. % ---------------- Font lookup ---------------- %
  1159.  
  1160. /fonttypeprocs mark        % <font-resource> -proc- <font>
  1161.   /Type0 /buildType0 cvx
  1162.   /Type1 /buildType1 cvx
  1163.   /MMType1 1 index
  1164.   /Type3 /buildType3 cvx
  1165.   /TrueType /buildTrueType cvx
  1166.   /CIDFontType0 /buildCIDType0 cvx
  1167.   /CIDFontType2 /buildCIDType2 cvx
  1168. .dicttomark readonly def
  1169.  
  1170. /resourcefont            % <font-resource> resourcefont <font>
  1171.  { dup /PSFont .knownget
  1172.     { /FID .knownget { type /fonttype eq } { false } ifelse }
  1173.     { false }
  1174.    ifelse
  1175.     { /PSFont get
  1176.     }
  1177.     { dup dup /FontDescriptor knownoget
  1178.        {    % Stack: font-res font-res font-desc
  1179.      dup /FontFile knownoget
  1180.       { exch pop readtype1 true }
  1181.       { dup /FontFile2 knownoget
  1182.          { exch pop readtruetype true }
  1183.          { /FontFile3 knownoget
  1184.         { dup /Subtype get fontloadprocs exch get exec true }
  1185.         { false }
  1186.            ifelse
  1187.          }
  1188.         ifelse
  1189.       }
  1190.      ifelse
  1191.        }
  1192.        { false }
  1193.       ifelse
  1194.         % Stack: font-res font-res false
  1195.         %  -or-: font-res font true
  1196.       not
  1197.        { dup /Subtype get fonttypeprocs exch get exec }
  1198.       if
  1199.       2 copy /PSFont exch put
  1200.       exch pop
  1201.     }
  1202.    ifelse
  1203.  } bdef
  1204.  
  1205. drawopdict begin
  1206.   /d0 {
  1207.     .adjustcharwidth setcharwidth
  1208.   } bdef
  1209.   /d1 {
  1210.     6 -2 roll .adjustcharwidth 6 2 roll setcachedevice
  1211.   } bdef
  1212.   /Tf {
  1213.     1 index Page /Font rget not { 1 index /invalidfont signalerror } if
  1214.     resourcefont exch Tf pop
  1215.   } bdef
  1216. end
  1217.  
  1218. end            % pdfdict
  1219. end            % GS_PDF_ProcSet
  1220. .setglobal
  1221.